
import { App } from "../../../../src/App";
import Map from "../../../../src/core/Map";
import { PokerData, PokerType, SpecialValue } from "../../../src/BaseLogic";
import BaseSingle from "../../../src/BaseSingle";
import GameLogic from "./GameLogic";
import { CallScore, GameModule, LandlordEvents, Ready, CreateLandlord, Discard, Settlement, PlayerIdentity, Deal } from "./GameModule";
import Robot from "./Robot";

class CSingleGame extends BaseSingle{
    private _hands:Map<number,PokerData[]> = new Map<number,PokerData[]>();
    private _callScore:Map<number,number> = new Map<number,number>();
    private _countScore:Map<number,number> = new Map<number,number>(); // 出牌计分
    private _landlord:CallScore = null;
    private _landlordPlayCount; // 地主出牌次数
    private _isGameOver:boolean = false;
    
    protected onEntry(){
        const leftRobot = this.createOneRobot<Robot>(Robot,1);
        const rightRobot = this.createOneRobot<Robot>(Robot,2);
        this._players.inset(0,{seat:0, user:GameModule.userInfo,obj:null}); 
        this._players.inset(1,{seat:0, user:leftRobot.info,obj:leftRobot}); 
        this._players.inset(2,{seat:0, user:rightRobot.info,obj:rightRobot});
        App.Event.emit(LandlordEvents.EC_GAME_START);

        let count:number = 0;
        App.Event.on(LandlordEvents.EC_READY,(data:Ready)=>{
            console.log(`SingleGame.ready:${JSON.stringify(data)}`);
            if (++count === GameModule.MaxSeat){
                setTimeout(() => {
                    this._deal();
                    count = 0;
                }, 2000);
            }
        },this);

        App.Event.on(LandlordEvents.EC_CALL,(data:CallScore)=>{
            console.log(`SingleGame.call:${JSON.stringify(data)}`);
            this._callScore.inset (data.seat,data.score);
            const tmpArr = this._callScore.sort((a,b)=>{return b.Val-a.Val});
            
            // 产生地主
            if (this._callScore.size === GameModule.MaxSeat || data.score >= 3){
                // 没人叫分重新开始
                if (tmpArr[0].Val < 1){
                    this._deal();
                    return ;
                }

                setTimeout(() => {
                    this._landlord = {seat:tmpArr[0].Key,score:tmpArr[0].Val,next:-1};
                    const pkg:CreateLandlord = {
                        seat:this._landlord.seat,
                        score:this._landlord.score,
                        cards:this._hands.find(3).slice(0),
                    };
                    App.Event.emit(LandlordEvents.EC_BUILD_BANKER,pkg);
                    this._hands.find(3).splice(0,3);
                }, 3000);
            } else {
                setTimeout(()=>{
                    const pkg:CallScore = {
                        seat:data.seat,
                        score:data.score,
                        next:GameModule.getNext(data.seat)
                    };
                    App.Event.emit(LandlordEvents.EC_NOTICE_CALL,pkg);
                },2000);
            }
        },this);

        App.Event.on(LandlordEvents.EC_DISCARD,(data:Discard)=>{
            if (this._isGameOver) return ;
            console.log(`SingleGame.discard:${JSON.stringify(data)}`);
            this._pokerTypeSocre(data.seat,data.cards);
            const hands:PokerData[] = this._hands.find(data.seat);
            for (let card of data.cards){
                const index = hands.indexOf(card);
                index > -1 && hands.splice(index,1);
            }

            this._isGameOver = hands.length < 1;
            // 牌出完，游戏结束
            if (this._isGameOver){  
                const pkg:Discard = {
                    cards:data.cards,
                    seat:data.seat,
                    next:-1,
                    delayTime:0
                };
                App.Event.emit(LandlordEvents.EC_NOTICE_DISCARD,pkg);

                setTimeout(() => {
                    this._gameOver(data.seat);
                    this._isGameOver = false;
                }, 2000);
            } else {
                const nextSeat = GameModule.getNext(data.seat);
                const pkg:Discard = {
                    cards:data.cards,
                    seat:data.seat,
                    next:nextSeat,
                    delayTime:nextSeat === 0 ? GameModule.MaxWaitTime:App.Util.random(3,6)
                };
                App.Event.emit(LandlordEvents.EC_NOTICE_DISCARD,pkg);

                data.seat === this._landlord.seat && this._landlordPlayCount++;
            }
        },this);
    }
    protected onExit(){
        this._players.forEach((it)=>{
            if (it.Val.obj){
                this._idleRobots.push(it.Val.user);
                it.Val.obj.destroy();
                delete it.Val.obj;
            }
        });
        
        this._cleanData();
        this._roomData = null;
        this._players.clear();
        App.Event.offAll(this);
    }

    private _deal(){
        this._cleanData();
        this._isPlaying = true;
        this._isGameOver = false;

        // 将扑克牌乱序后分成三个玩家手牌和三张底牌
        this._hands.inset(0,[]),this._hands.inset(1,[]),this._hands.inset(2,[]),this._hands.inset(3,[]);
        const newArr = App.Util.confusionArray(GameLogic.list2Pokers(GameModule.pokerTable.slice(0)));
        for (let i = 0; i < newArr.length; i++) {
            if (i <= 50) {
                if (i % 3 === 0) this._hands.find(0).push(newArr[i]);
                else if (i % 3 === 1) this._hands.find(1).push(newArr[i]);
                else if (i % 3 === 2) this._hands.find(2).push(newArr[i]);
            }
            else this._hands.find(3).push(newArr[i]);
        }

        const _first = App.Util.random(0,2);
        let tmp = [];
        for (let i = 0; i < GameModule.MaxSeat; ++i){
            tmp.push({
                seat:i,
                cards:this._hands.find(i).slice(0),
                first:_first
            });
        }
        const pkg:Deal = {
            info:tmp.slice(0),
            baseCards:this._hands.find(3).slice(0),
        }
        App.Event.emit(LandlordEvents.EC_DEAL,pkg);

        // 确保发牌动画播放结束
        setTimeout(() => {
            App.Event.emit(LandlordEvents.EC_NOTICE_CALL,{
                next:_first,
                seat:-1,
                score:-1,
            });
        }, 7000);
    }

    private _cleanData(){
        this._hands.clear();
        this._callScore.clear();
        this._countScore.clear();
        this._landlord = null;
        this._landlordPlayCount = 0;
        this._isPlaying = false;
    }

    private _pokerTypeSocre(seat:number,cards:PokerData[]){
        if (cards.length < 1 || (seat < 0 || seat >= GameModule.MaxSeat)) return ;
        const discard = GameLogic.getUnion(cards);
        let tmpScore = this._countScore.find(seat) || 0;
        switch (discard.type){
            case PokerType.joker:tmpScore += 500; break;
            case PokerType.bomb : tmpScore += 400; break;
            case PokerType.progression_pairs : tmpScore += 200; break;
            case PokerType.plane: 
            case PokerType.plane_single:
            case PokerType.plane_pair:
            case PokerType.plane_pairs:tmpScore += 300; break;
            default : {
                for (let it of cards){
                    it.val === SpecialValue.num_2 && (tmpScore += 100);
                }
            }
        }

        tmpScore > 0 && this._countScore.inset(seat,tmpScore);
    }

    private _gameOver(endSeat:number){   
        this._callScore.sort((a,b)=>{return b.Val-a.Val});
        let totalScore:number = GameModule.roomData.BetMin * this._callScore.iterable[0].Val;   
        // 农民手牌
        let _farmerHands = 0;
        this._hands.forEach((hands,idx:number)=>{
            idx !== this._landlord.seat && (_farmerHands += hands.Val.length);
        }) 

        let springFlag=-1;
        // 春天
        if (_farmerHands === 34){
            totalScore += 500;
            springFlag = 0;
        }

        // 反春天翻倍
        if (this._landlordPlayCount === 1 && endSeat !== this._landlord.seat) {
            totalScore += 400;
            springFlag = 1;
        }

        for (let it of this._countScore.iterable){
            totalScore += it.Val;
        }

        let landloardDelta = 0;
        let farmerDelta = 0;
        if (endSeat === this._landlord.seat){            
            landloardDelta = totalScore;
            farmerDelta = -1 * Math.floor(totalScore*0.5);
        } else {
            landloardDelta = -2 * totalScore;
            farmerDelta = 1 * totalScore;
        }
        let tmp =[];
        for (let i = 0; i < GameModule.MaxSeat; ++i){
            tmp.push({
                name:this._players.find(i).user.UserName, // 玩家名
                seat:i, 
                flag:this._landlord.seat === i ? PlayerIdentity.landlord : PlayerIdentity.farmer,  
                score:this._landlord.seat === i ? landloardDelta : farmerDelta
            });
        }

        const pkg:Settlement = {
            win:landloardDelta > 0 ? PlayerIdentity.landlord:PlayerIdentity.farmer,
            spring:springFlag,
            info:tmp.slice(0),
        };
        App.Event.emit(LandlordEvents.EC_GAME_OVER,pkg);
        this._cleanData();
    }
}
export const SingleGame: CSingleGame = CSingleGame.getInstance<CSingleGame>(CSingleGame);